<?php
use frontend\modules\yii2\widgets\layouts\markdown\Markdown;
/* @var $this \yii\web\View */
$this->title = 'assetManager资源管理组件的学习和使用-Components组件';
$this->registerMetaTag([
    'name' => 'keywords',
    'content' => 'yii,yii2,框架,应用组件,Components,使用,教程,assetManager'
]);
$this->registerMetaTag([
    'name' => 'description',
    'content' => 'AssetManager组件是对js/css/image等资源的管理组件，它可以帮助我们对静态资源进行分块管理，但是最终实现公共访问权限。'
]);

$html = [
    "概述" => <<<HTML
# AssetManager资源管理组件的学习和使用
`AssetManager`组件负责管理js/css/image等静态资源，以合理的方式整合这些资源，并赋予相应的访问权限。

HTML,
    "config" => <<<HTML
## 配置举例 id=config
`AssetManager`组件的全局配置举例如下：
```php
[
    'components' => [
        'assetManager' => [
            'bundles' => [
                'yii\bootstrap\BootstrapAsset' => [
                    'css' => [],
                ],
            ],
            'assetMap' => [
                'jquery.min.js' => '@web/js/jquery/jquery.js',
            ]
        ]
    ],
]
```

HTML,
    "bundels" => <<<HTML
## 修改资源包（bundels） id=bundels
在`vendor`扩展包中，有默认的资源包可以使用，但是这个目录下的资源包是不具备可编辑权限的，而`bundels`这个属性允许对这些资源包进行调整，比如说：
```php
namespace yii\bootstrap;

use yii\web\AssetBundle;

class BootstrapAsset extends AssetBundle
{
    public \$sourcePath = '@bower/bootstrap/dist';
    public \$css = [
        'css/bootstrap.css',
    ];
}
```
上述资源包定义了`bootstrap.css`这个css资源的所在位置，您只需要在view视图中注册资源包即可使用它，Yii会把`bootstrap.css`复制一份放到可访问的目录下（`web/assets/`），并在页面中自动添加引用：
```php
BootstrapAsset::register(\$this);
```
在页面中的表现一般如下：
```html
<link href="/assets/e836725e/css/bootstrap.css" rel="stylesheet">
```

**那你可能会问：为什么这么麻烦定义资源包来使用资源而不是直接手动引入资源呢？**

引入资源包的目的有如下两个：
- 有些资源有相互依赖关系，即谁先加载谁后加载有明确的要求，而资源包允许设定依赖；
- 资源包的引入，使yii能够以vendor扩展的方式管理资源。

在很多情况下，我们需要修改资源包提供的样式，此时我们可以通过`bundels`这个属性来完成修改：
```php
'components' => [
    'assetManager' => [
        'bundles' => [
            'yii\bootstrap\BootstrapAsset' => [
                'css' => [
                    // 在指定路径中查找文件，目录为：@bower/bootstrap/dist
                    'css/bootstrap.css',
                    // 在根目录中查找文件，目录为：frontend/web/css
                    '/css/bootstrap3.css'
                ],
            ],
        ],
    ]
],
```
我们知道`BootstrapAsset`原来只提供了一个css文件，但是我们通过上述配置，使`BootstrapAsset`资源包绑定了另一个`frontend/web/css/bootstrap3.css`文件来实现自定义的样式。
HTML,
    "map" => <<<HTML
## 资源替换（assetMap） id=assetMap
我们可以使用`assetMap`属性来替换指定名称的资源：
```php
'components' => [
    'assetManager' => [
        'assetMap' => [
            'css/bootstrap.css' => '@web/css/bootstrap3.css',
        ]
    ]
],
```
上述代码会将页面中以`css/bootstrap.css`结尾的文件替换为`bootstrap3.css`。
HTML,
    "linkAssets" => <<<HTML
## 禁用copy资源（linkAssets） id=linkAssets
Yii对资源的默认使用方式是拷贝，即：会把涉及到的资源（css/js/images）拷贝到web可访问的目录下（通常是：@web/assets/）。但是这样做就有个不方便的地方：当我们在开发自定义资源包的时候，每次变动`css/js`都需要删除`@web/assets/`下的副本才能使变动生效，介于此原因`linkAssets`横空出世，它默认是`false`，当被设置为`true`时，便不再进行拷贝动作，而是使用了软连接，如下：
```shell
lvzmen:cms.lvzmen.com$ ls -al frontend/web/assets/

lrwxrwxrwx 1 ... 31ecc5e3 -> /app/frontend/modules/yii2/widgets/layouts/dockerdoc/assets
lrwxrwxrwx 1 ... 481fc1d9 -> /app/vendor/yiisoft/yii2/assets
lrwxrwxrwx 1 ... 8fbb27dc -> /app/vendor/bower-asset/jquery/dist
lrwxrwxrwx 1 ... 99ca6996 -> /app/frontend/modules/yii2/widgets/layouts/sidebar/assets
lrwxrwxrwx 1 ... efb476dc -> /app/frontend/modules/yii2/widgets/layouts/anchor/assets
lrwxrwxrwx 1 ... fca309d7 -> /app/frontend/modules/yii2/widgets/layouts/markdown/assets
lrwxrwxrwx 1 ... fe7a536 -> /app/vendor/bower-asset/bootstrap/dist
```

这在开发环节非常有用，您可以使用如下配置根据只在开发环境下启用：
```php
if(YII_ENV_DEV){
    \$config['components']['assetManager']['linkAssets'] = true;
}
```
**填坑：**
要知道测试环境或者生产环境下是采用copy机制访问资源的，当我们修改了某个css/js文件后，开发环境由于直接使用引用可以即时生效，但是切换到其他环境时依然会使用已经拷贝的资源，这就导致资源更新失败，这个问题可以通过阅读[更新浏览器资源缓存](#appendTimestamp)来解决。

HTML,
    "appendTimestamp" => <<<HTML
## 更新浏览器资源缓存 id=appendTimestamp
我们知道浏览器会缓存静态资源文件，这会导致我们的资源文件更新失败，面对这种情况的解决方案就是在资源文件连接上加上一个随机版本号，如：
```html
<link href="/assets/31ecc5e3/css/bootstrap3.css?v=1639963195" rel="stylesheet">
```
我们可以通过`appendTimestamp`这个属性做到这一点：
```php
'components' => [
    'assetManager' => [
        'appendTimestamp' => true
    ]
],
```
> **注意：**只有在资源包管理文件（如：/frontend/assets/AppAsset.php）发生修改的情况下才会触发时间戳变更，也就是说`AppAsset`所管理的静态资源（css/js）发生变化时，是无法直接触发`?v=timestamp`变更的，因此需要手动修改一下资源对应的包管理文件（如：AppAsset.php），改什么都好，新增一个空白行也行。
HTML,
    "" => <<<HTML

HTML,

];

echo Markdown::widget(["content" => implode("\n", $html)]);

